package model;

import datacontainer.ImmuTable;
import factory.Factory;
import java.util.ArrayList;
import java.util.List;
import model.action.AbstractAction;
import model.datareader.AbstractReader;


/**
 * This is the main class in the Model API.
 * 
 * @author Michael Deng
 * @author Jei Min Yoo
 */
public class DataManager {

    private static final int FILE_TYPE_LENGTH = 3;

    private Factory<AbstractReader> myReaderFactory;
    private Factory<AbstractAction> myActionFactory;
    private ImmuTable myRawData;
    private ImmuTable myWorkSpace;

    /**
     * Constructor for the Model class
     * instantiates reader and action factories.
     */
    public DataManager () {
        myReaderFactory = new Factory<AbstractReader>("model.datareader", 
                "File is bad!");
        myActionFactory = new Factory<AbstractAction>("model.action", 
                    "Unable to create new action!");
        resetWorkspace();
    }

    /**
     * creates a new workspace
     * 
     */
    public void createWorkspace () {
        resetWorkspace();
        populateWorkspace();
    }

    private void populateWorkspace () {
        for (String header : myRawData.getHeaders()) {
            myWorkSpace.getHeaders().add(header);
        }
        for (String type : myRawData.getTypes()) {
            myWorkSpace.getTypes().add(type);
        }
        for (int i = 0; i < myRawData.getNumColumns(); i++) {
            List<String> listToAdd = new ArrayList<String>();
            for (int j = 0; j < myRawData.getColumn(i).size(); j++) {
                listToAdd.add(myRawData.getColumn(i).get(j));
            }
            myWorkSpace.getData().add(listToAdd);
        }
    }

    /**
     * resets raw data. used when user change input file.
     * 
     * @param path file path to the data file
     */
    public void resetRawData (String path) {
        AbstractReader reader = myReaderFactory.getObject(
            path.substring(path.length() - FILE_TYPE_LENGTH).toUpperCase() + "Reader");
        reader.readFile(path);
        myRawData = reader.returnResult();
    }

    /**
     * Clears the workspace and then recopies all the raw data from storage to
     * workspace
     */
    public void resetWorkspace () {
        myWorkSpace =
                new ImmuTable(new ArrayList<String>(), new ArrayList<String>(),
                              new ArrayList<List<String>>());
    }

    /**
     * 
     * @return returns an ImmuTable data structure.
     */
    public ImmuTable returnResult () {
        myWorkSpace.makeUnmodifiable();
        return myWorkSpace;
    }

    /**
     * must use correct class name for actionName ex) AddColumn, DeleteColumn
     * etc.
     * 
     * @param column column of interest
     * @param actionName name of action class
     * @param conditions conditions for a specific action. May not apply to all
     *        actions.
     */
    public void dataAction (String column, String actionName, List<String> conditions) {
        AbstractAction a = myActionFactory.getObject(actionName);
        a.setInput(column, conditions);
        a.execute(myWorkSpace, myRawData);
    }
}
 